/**
 *
 */
package com.bot.core;

import java.sql.SQLException;
import java.util.Timer;
import java.util.TimerTask;

import org.jibble.pircbot.Colors;

/**
 * The timer that controls the button
 * @author gcanosa
 */
public class TimerBot {

	final static int timeLimit = 108 * 60;
	final static int timeCanBePushed = 4 * 60;
	final static int explodeTime = 0;
	final static int period = 1000;
	final static int[] alertTime = new int[] {timeLimit, 108, 80, 60, 40, 20, 8, 4, 1};

	int secs;
	LostBot bot;
	//final String channel = bot.getCountdownChannel();
	final String topicMessage = " - Time is ticking, enter the Numbers to save the world - Triggers are: .time / .info / .ratio / .hof / .user <nick>";

	public TimerBot(LostBot bot) {
		this.bot = bot;
		this.reset();
	}

	public int getSecs() {
		return secs;
	}

	public void setSecs(int secs) {
		this.secs = secs;
	}

	private void reset() {
		this.secs = timeLimit;
	}

	public void run() {
		final Timer timer = new Timer();
	    timer.scheduleAtFixedRate(new TimerTask() {

	        public void run() {

	        	checkAndSendAlerts();

	        	// System.out.println(secs--/60);
	        	// debug.
	            secs--;

	            // TODO clean this up, reuse canBePushed and canFailSafeKeyBeEntered
	            if ( secs == 0) {
	            	bot.setTopic(bot.getCountdownChannel(),
	            			"|[" + Colors.RED + Colors.BOLD + Colors.REVERSE + Colors.BLACK + "ƎƩƷ" + Colors.NORMAL + "|" + Colors.RED + Colors.BOLD + Colors.REVERSE + Colors.WHITE + "ßƾ" + Colors.NORMAL + "]| SYSTEM FAILURE"
	            			+ Colors.RED + Colors.BOLD + " - NOBODY PUSHED THE BUTTON - THE END OF THE WORLD IS COMING.");
	            	try {
						bot.createFailsafeKeyAndUpdateDB(new java.util.Date().toString());
					} catch (SQLException e) {
						System.out.println("DB couldn't be updated so the new record hasn't been added.");
						e.printStackTrace();
					}
	            	bot.sendMessage(bot.getCountdownChannel(),
	            			"Enter: " + Colors.BOLD + Colors.BLUE
	            			+ "http://lamp.50carleton.com/~ethernet/failsafe.php and get the valid Key to avoid the electromagnetic pulse within 60 seconds");
	            } else if ( secs >= -4 && secs < 0 ) {
	        		bot.sendMessage(bot.getCountdownChannel(), Colors.BOLD + Colors.RED + "SYSTEM FAILURE - SYSTEM FAILURE -  SYSTEM FAILURE - SYSTEM FAILURE - SYSTEM FAILURE - SYSTEM FAILURE - SYSTEM FAILURE - SYSTEM FAILURE - SYSTEM FAILURE - SYSTEM FAILURE - SYSTEM FAILURE - SYSTEM FAILURE - SYSTEM FAILURE");
	            } else if (secs == -360) {
	        		bot.setMode(bot.getCountdownChannel(), "+mp");		// close bot.getCountdownChannel()
	        		bot.setTopic(bot.getCountdownChannel(), Colors.RED + Colors.BOLD + "The Swan has EXPLODED, WORLD IS OVER, NO KEY HAS BEEN ENTERED - FAILSAFE HASN'T BEEN USED");
	        		try {
						bot.addFailureToDB();
					} catch (SQLException e) {
						e.printStackTrace();
					}
	        	} else if (secs == -21600) {								// counter restarted 108 mins remaining.
	        		secs = timeLimit;
	        		bot.setMode(bot.getCountdownChannel(), "-mp");			// open channel and restart game.
	        		bot.blankLastKey();										// blank key to start a new game.
	        	}
	        }
	    }, 0, period);
	}

	/**
	 * Looks in alertTime to see if its time to show an alert
	 */
	private void checkAndSendAlerts() {
		for (int time : alertTime) {
			if (this.secs == time * 60) {
				bot.setTopic(bot.getCountdownChannel(), getCurrentTimeString() + topicMessage);
				return;
			}
		}
	}

	/**
	 * Pushes the button
	 * @param pusher the one who pushed it
	 * @throws NotYetException Button cant be pushed now
	 * @throws SQLException 
	 */
	public void pushButton(String pusher) throws NotYetException, SQLException {
		if (!this.canBePushed())
			throw new NotYetException();
		else {
			this.reset();
			bot.sendMessage(bot.getCountdownChannel(), pusher + Colors.GREEN + " has pushed the button.");
	    	bot.addUserPush(pusher, new java.util.Date().toString());
	    	bot.addPushToDB();
	    	this.reset();
		}
	}

	/**
	 * Enters the fail safe key
	 * @param keyOwner the one who owns the key
	 * @throws NotYetException Key cannot be entered yet
	 * @throws SQLException 
	 */
	public void enterFailSafeKey(String keyOwner) throws NotYetException, SQLException {
		if (!this.canFailSafeKeyBeEntered())
			throw new NotYetException();
		else {
			this.reset();
			bot.sendMessage(bot.getCountdownChannel(), keyOwner + Colors.GREEN + " has entered the FailSafe key and saved the world.");
	    	bot.addUserPush(keyOwner, new java.util.Date().toString());
	    	bot.addFailSafeToDB();
	    	this.reset();
		}
	}

	/**
	 * Tells if button can be pushed
	 * @return true if it can
	 */
	public boolean canBePushed() {
		return this.secs <= timeCanBePushed && this.secs > explodeTime;
	}

	/**
	 * Tells if the key can be entered
	 * @return true if it can
	 */
	public boolean canFailSafeKeyBeEntered() {
		return this.secs < 0 && this.secs >= -360;
	}

	/**
	 * Same as getTimeString, but with current time
	 * @return
	 * @see getCurrentTimeString()
	 */
	public String getCurrentTimeString() {
		int mins = this.getMins();
		return this.getTimeString(mins, this.secs - mins * 60);
	}

	/**
	 * Obtains the irc string representation of the timer
	 * @param minutes
	 * @param seconds
	 * @return
	 */
	public String getTimeString(int minutes, int seconds) {
		StringBuilder time = new StringBuilder( "|[" + Colors.BOLD + Colors.BLACK + Colors.REVERSE + Colors.WHITE );
		if ( seconds >= 0) {
			if (minutes < 10)
				time.append("00");
			else if (minutes < 100)
				time.append("0");
	
			time.append(minutes + Colors.NORMAL + "|" + Colors.BOLD + Colors.WHITE + Colors.REVERSE + Colors.BLACK);
	
			if (minutes < 4) {
				if (seconds < 10)
					time.append("0");
	
				time.append(seconds);
			} else {
				time.append("00");
			}
		} else {
			time.append(Colors.RED + Colors.BOLD + Colors.REVERSE + Colors.BLACK + "ƎƩƷ" + Colors.NORMAL + "|" + Colors.RED + Colors.BOLD + Colors.REVERSE + Colors.WHITE + "ßƾ");
		}
			
		time.append(Colors.NORMAL + "]|");


		return (time.toString());
	}

	public int getMins() {
		return getSecs() / 60;
	}
}
